package com.wzw.basics.concurrent.util;

import java.util.concurrent.*;

/**
 * 常用的线程框架
 *
 * @author Wangzhiwen
 */
public class CommonUtils {

}

/**
 * CountDownLatch 阻塞一些线程知道指定的线程运行完成调用downLatch方法后，内部计数减为0时才会被唤醒
 * 例如：火箭倒计时发射
 * 底层原理：AQS框架共享锁的资源释放
 */
class CountDownLatchDemo {

    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        m1(10, countDownLatch);
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            // ignore
        }
        System.out.println(Thread.currentThread().getName() + " 等待其他线程执行完成后在执行");
    }

    public static void m1(int count, CountDownLatch countDownLatch) {
        for (int i = 0; i < count; i++) {
            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(ThreadLocalRandom.current().nextInt(1, 3));
                } catch (InterruptedException e) {
                    // ignore
                }
                System.out.println(Thread.currentThread().getName() + " 执行完成");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
    }

}

/**
 * CyclicBarrier 让一组线程达到一个屏障是被阻塞，只有最后一个线程达到屏障后。屏障才会被打开，所有被拦截的线程才会继续下去
 * 例如：七龙珠全部收集完后才能召唤神龙
 * 底层原理：依赖condition条件类，完成线程间的通信。
 */
class CyclicBarrierDemo {

    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
            System.out.println("所有线程均以执行完成任务，召唤神龙");
        });
        m1(cyclicBarrier);
    }

    public static void m1(CyclicBarrier cyclicBarrier) {
        for (int i = 1; i < 8; i++) {
            final int temp = i;
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " 收集到第" + temp + "颗龙珠");
                // 阻塞屏障
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException ignored) {
                    // ignore
                }
            }, String.valueOf(i)).start();
        }
    }

}

/**
 * semaphore 信号量，多个共享资源的互斥使用与限制并发数.允许n个任务同时访问这个资源。
 * 例如：抢车位场景，10辆车6个车位
 * 底层原理：AQS与自旋阻塞
 */
class SemaphoreDemo {

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(6, false);// 非公平锁
        m1(semaphore);
    }

    public static void m1(Semaphore semaphore) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire(); //抢占资源

                    System.out.println(Thread.currentThread().getName() + " 抢到车位，开始停车"); // 做事情

                    TimeUnit.SECONDS.sleep(2); // 停两秒

                    System.out.println(Thread.currentThread().getName() + " 离开车位"); // 执行完毕
                } catch (Exception e) {
                    // ignore
                } finally {
                    semaphore.release(); // 释放资源
                }
            }, String.valueOf(i)).start();
        }
    }

}
